package com.zmn.oms.third.sogou.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.DefaultEcProductQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dictionary.GlobalDict;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.baidumap.LngLatLocation;
import com.zmn.oms.model.dto.order.create.CreateOrderFailMessage;
import com.zmn.oms.model.dto.order.proxy.CreateOrderDTO;
import com.zmn.oms.model.dto.product.ChannelProductMapDTO;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.entity.trace.SogouOrderTrace;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.services.interfaces.order.OrderChangeService;
import com.zmn.oms.services.interfaces.trace.ChannelOrderTraceService;
import com.zmn.oms.third.base.util.ThirdOrderUtil;
import com.zmn.oms.third.sogou.SogouConsts;
import com.zmn.oms.third.sogou.SogouProductMap;
import com.zmn.oms.third.sogou.dto.SogouClueData;
import com.zmn.oms.third.sogou.dto.SogouClueFormItem;
import com.zmn.oms.third.sogou.service.SogouClueService;
import com.zmn.oms.zmn.business.interfaces.discount.ChannelDiscountService;
import com.zmn.oms.zmn.business.interfaces.product.ProductMappingBService;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 搜狗搜索渠道线索处理的接口实现
 *
 * @author xiewenbing
 * @date  2021/04//27 18:00
 */

@Slf4j
@Service("sogouClueService")
public class SogouClueServiceImpl implements SogouClueService {

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected AreaListRemoteService areaListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ProductForeignListRemoteService productForeignListRemoteService;

    @Autowired
    private ProxyOrderBService proxyOrderBService;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;
    @Autowired
    private OrderChangeService orderChangeService;
    @Autowired
    private BaiduMapBService baiduMapBService;
    @Autowired
    protected ZsOrderWorkQueryBService zsOrderWorkQueryBService;
    @Autowired
    private ChannelDiscountService channelDiscountService;
    @Autowired
    private ChannelOrderTraceService channelOrderTraceService;
    @Autowired
    private ProductMappingBService productMappingBService;
    @Resource
    private RedisManager redisManager;

    /**
     * 处理接受的线索列表
     *
     * @param channelId
     * @param sogouClueList
     * @throws OmsBaseException
     */
    @Override
    public void handleClueList(Integer channelId, List<SogouClueData> sogouClueList) throws OmsBaseException {

        if (!SogouConsts.POWER_ON) {
            log.info("【{}】服务暂不支持", SogouConsts.CHANNEL_NAME);
            throw new OmsBaseException("服务暂不支持");
        }

        if (CollectionUtils.isEmpty(sogouClueList)) {
            log.info("【{}】线索列表为空", SogouConsts.CHANNEL_NAME);
            throw new OmsBaseException("参数错误");
        }

        for (SogouClueData sogouClue : sogouClueList) {

            this.handleSogouClue(channelId, sogouClue);
        }
    }

    /**
     * 处理推送的线索信息
     *
     * @param channelId
     * @param sogouClueData
     * @throws OmsBaseException
     */
    protected void handleSogouClue(Integer channelId, SogouClueData sogouClueData) {

        if (Objects.isNull(sogouClueData)) {
            return;
        }

        // 线索重复检测
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(sogouClueData.getClueId().toString(),channelId);
        if (Objects.nonNull(zsOrderWorkVO)) {

            log.info("【{}】【{}】重复的订单线索【{}】", SogouConsts.CHANNEL_NAME, channelId,sogouClueData.getClueId());
            return;
        }

        if (this.setRedisClueData(sogouClueData.getClueId(),GlobalConsts.YES) > 1) {
            log.info("【{}】【{}】相同的订单线索正在处理【{}】", SogouConsts.CHANNEL_NAME, channelId,sogouClueData.getClueId());

            this.setRedisClueData(sogouClueData.getClueId(),GlobalConsts.NO);
            return;
        }

        log.info("【{}】处理线索- 【{}】【{}】", SogouConsts.CHANNEL_NAME, channelId, sogouClueData.toString());

        do {

            // 生成创建订单信息
            CreateOrderDTO createOrderDTO = buildCreateOrderDTO(channelId, sogouClueData);
            if (Objects.isNull(createOrderDTO)) {
                break;
            }

            boolean result = false;
            // 验证订单信息的完整
            if (!isOrderInfoIntact(createOrderDTO)) {

                // 推送线索到呼叫中心
                result = pushOrderCallCenter(createOrderDTO, JSON.toJSONString(sogouClueData));
            } else {
                // 创建订单
                OrderWork orderWork = createOrder(createOrderDTO);

                if (Objects.nonNull(orderWork)) {
                    // 保存订单渠道溯源数据
                    SogouOrderTrace sogouOrderTrace = BeanMapper.map(sogouClueData,SogouOrderTrace.class);
                    sogouOrderTrace.setOrderId(orderWork.getOrderId());
                    sogouOrderTrace.setChannelId(channelId);
                    channelOrderTraceService.addSogouOrderTrace(sogouOrderTrace);
                    result = true;
                }
            }

            if (!result) {
                break;
            }

            // 删除缓存数据
            this.setRedisClueData(sogouClueData.getClueId(),GlobalConsts.NONE);

            return;
        } while(false);

        // 修改线索缓存数据
        this.setRedisClueData(sogouClueData.getClueId(),GlobalConsts.NO);

        log.info("【{}】处理线索失败 - 【{}】【{}】", SogouConsts.CHANNEL_NAME, channelId, sogouClueData.toString());
    }

    /**
     * 生成创建订单的对象
     *
     * @param channelId
     * @param sogouClueData
     * @return
     */
    protected CreateOrderDTO buildCreateOrderDTO(Integer channelId, SogouClueData sogouClueData) {

        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        // 渠道id
        createOrderDTO.setChannelId(channelId);

        // 预约时间
        createOrderDTO.setDutyTime(ThirdOrderUtil.getDefaultDutyTime());

        // 外部订单id - 线索id
        createOrderDTO.setOuterId(sogouClueData.getClueId().toString());

        // 平台标识
        createOrderDTO.setPlat(GlobalConsts.PLAT_MARK_ZMN);

        // 联系人性别
        createOrderDTO.setGender(GlobalDict.GENDER_NO);

        // 禁止弃单
        createOrderDTO.setDisableDiscard(GlobalConsts.NO);

        // 操作者
        createOrderDTO.setOperator("系统");

        // 操作者id
        createOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        // 操作者类型
        createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        // 工单录入方式
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        // 用户联系电话
        if (StringUtil.isNotBlank(sogouClueData.getPhoneNumber())) {
            createOrderDTO.setTelephone(sogouClueData.getPhoneNumber());
        }

        // 城市、用户地址
        String city = sogouClueData.getRegion();
        String address = "";

        // 产品信息
        String product = "";

        // 解析提交的表单
        for (SogouClueFormItem clueFormItem : sogouClueData.getData()) {

            String label = clueFormItem.getLabel();
            String value = clueFormItem.getValue();
            if (StringUtil.isBlank(label) || StringUtil.isBlank(value)) {
                continue;
            }

            if (label.indexOf(SogouConsts.LABEL_NAME) >= 0) {
                createOrderDTO.setContactName(value);
            } else if(label.indexOf(SogouConsts.LABEL_PHONE) >= 0) {
                createOrderDTO.setTelephone(value);
            } else if(label.indexOf(SogouConsts.LABEL_ADDRESS) >= 0) {
                address = value;
            } else if(label.indexOf(SogouConsts.LABEL_PRODUCT) >= 0) {
                product = value;
            } else if(label.indexOf(SogouConsts.LABEL_CITY) >= 0) {
                city = value;
            }
        }

        // 地址、经纬度、城市
        fillOrderAddress(createOrderDTO, city + address);

        // 产品信息
        fillOrdreProduct(createOrderDTO, product);

        // 日志
        StringBuilder sbOperatorLog = new StringBuilder();
        sbOperatorLog.append("<br/>  线索id：").append(sogouClueData.getClueId()).
                append("<br/>  表单id：").append(sogouClueData.getFormId()).
                append("<br/>  表单名称：").append(sogouClueData.getFormName()).
                append("<br/>  站点名称：").append(sogouClueData.getSiteName()).
                append("<br/>  页面名称：").append(sogouClueData.getPageName()).
                append("<br/>  流量渠道：").append(sogouClueData.getChannel()).
                append("<br/>  城市：").append(Optional.ofNullable(city).orElse("")).
                append("<br/>  详细地址：").append(Optional.ofNullable(address).orElse("")).
                append("<br/>  报修品类：").append(Optional.ofNullable(product).orElse("")).
                append("<br/>");

        createOrderDTO.setOperatorLogRemark(sbOperatorLog.toString());

        // 优惠 - 2021/6/1 至 2021/9/31 优惠5元
        channelDiscountService.tbsTempDiscountFiveYuan(createOrderDTO);
        return createOrderDTO;
    }

    /**
     * 判断订单中的地址，产品，客户联系电话是否完整
     * @param createOrderDTO
     * @return
     */
    protected boolean isOrderInfoIntact(CreateOrderDTO createOrderDTO) {

        // 经纬度
        if (Objects.isNull(createOrderDTO.getLongitude()) || Objects.isNull(createOrderDTO.getLatitude())) {
            return false;
        }

        // 联系电话
        if (StringUtil.isBlank(createOrderDTO.getTelephone())) {
            return false;
        }

        // 产品
        if (CollectionUtils.isEmpty(createOrderDTO.getOrderProductList())) {
            return false;
        }

        OrderProductDTO orderProductDTO = createOrderDTO.getOrderProductList().get(0);
        if (Objects.equals(orderProductDTO.getProductShowType(), GlobalConsts.YES)) {

            // 前台产品
            if (Objects.equals(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID, orderProductDTO.getShowProductId())) {
                return false;
            }
        } else {

            // 后台产品
            if (Objects.equals(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID, orderProductDTO.getProductId())) {
                return true;
            }
        }

        return true;
    }

    /**
     * 将不完整的订单数据推送到呼叫中心
     *
     * @param createOrderDTO
     * @param clueData
     */
    protected boolean pushOrderCallCenter(CreateOrderDTO createOrderDTO, String clueData) {

        if (Objects.isNull(createOrderDTO)) {
            return false;
        }

        log.info("【{}】将不完整的订单推送到呼叫中心【{}】【{}】", SogouConsts.CHANNEL_NAME, createOrderDTO.toString(),clueData);

        try {
            // 将线索转到呼叫中心去
            CreateOrderFailMessage createOrderFailMessage = new CreateOrderFailMessage();
            createOrderFailMessage.setChannelId(createOrderDTO.getChannelId());
            createOrderFailMessage.setTelephone(createOrderDTO.getTelephone());
            createOrderFailMessage.setContactName(createOrderDTO.getContactName());
            createOrderFailMessage.setAddress(createOrderDTO.getAddressClues());
            createOrderFailMessage.setProductName(createOrderDTO.getProductClues());
            createOrderFailMessage.setCityId(createOrderDTO.getCityId());
            createOrderFailMessage.setExtData(clueData);
            orderChangeService.orderCreateFailSyncToApi(createOrderFailMessage);

            return true;
        } catch (Exception e) {

            log.info("【{}】将订单推送到呼叫中心异常【{}】【{}】", SogouConsts.CHANNEL_NAME, e.getMessage(),e);
        }

        return false;
    }

    /**
     * 创建订单
     * @param createOrderDTO
     */
    protected OrderWork createOrder(CreateOrderDTO createOrderDTO) {

        try {

            // 创建订单
            OrderWork orderWork = proxyOrderBService.createOrder(createOrderDTO).getOrderWork();

            log.info("【{}】创建订单成功 【{}】", SogouConsts.CHANNEL_NAME, orderWork.getOrderId());

            // 工单自动流转
            workFlowContextBService.asyncAutoFlow(orderWork.getOrderId(),orderWork.getWorkId());

            return orderWork;

        } catch (OmsBaseException omsBaseException) {

            log.info("【{}】创建订单异常 【{}】【{}】", SogouConsts.CHANNEL_NAME, omsBaseException.getMessage(), omsBaseException.toString());

        } catch (Exception exception) {

            log.info("【{}】创建订单异常 【{}】【{}】", SogouConsts.CHANNEL_NAME, exception.getMessage(), exception.toString());
        }

        return null;
    }

    /**
     * 填充订单地址信息：将地址转换成符合我们自己系统使用的地址信息
     *
     * @param createOrderDTO
     * @param address
     */
    private void fillOrderAddress(CreateOrderDTO createOrderDTO, String address) {

        // 判断地址是否为空
        if (StringUtil.isBlank(address)) {
            return;
        }

        // 去掉空格,-和括号(包含括号里面内容)
        Pattern pattern = Pattern.compile("\\s+|-|（.*）|[(](.*)[)]");
        Matcher matcher = pattern.matcher(address);
        String userAddress = matcher.replaceAll("");

        // 具体地址放入address
        createOrderDTO.setAddress(userAddress);

        // street字段在数据库中不能为空
        createOrderDTO.setStreet("");

        // 记录线索中的完整地址信息，方便推送给呼叫中心
        createOrderDTO.setAddressClues(address);

        // 经纬度和城市id
        LngLatLocation location = baiduMapBService.location(userAddress);
        if (Objects.isNull(location)) {
            log.info("【{}】通过地址查询经纬度失败【{}】", SogouConsts.CHANNEL_NAME, userAddress);
            return;
        }

        Double lng = Double.valueOf(location.getLng());
        Double lat = Double.valueOf(location.getLat());

        try {
            ResponseDTO<AreaDRO> areaResponse = areaListRemoteService.getAreaByLatAndLng(lng, lat);
            AreaDRO areaDRO = areaResponse.getData();
            if (areaResponse.isSuccess() && Objects.nonNull(areaDRO)) {
                createOrderDTO.setCityId(areaDRO.getParentId());
                createOrderDTO.setLatitude(lat);
                createOrderDTO.setLongitude(lng);
            } else {
                log.info("【{}】通过经纬度查询城市失败【{}】【{}】", SogouConsts.CHANNEL_NAME, lng, lat);
            }

        } catch (Exception e) {
            log.info("【{}】通过经纬度查询城市异常【{}】【{}】", SogouConsts.CHANNEL_NAME, lng, lat);
        }
    }

    /**
     * 填充创建订单信息中的产品信息
     *
     * @param createOrderDTO
     * @param product
     */
    private void fillOrdreProduct(CreateOrderDTO createOrderDTO, String product) {

        if (StringUtil.isBlank(product)) {
            return;
        }

        createOrderDTO.setRemark(product);
        createOrderDTO.setProductClues(product);

        // productStr格式：家电维修,空调,定频挂机空调维修（2-3P）
        OrderProductDTO orderProduct = new OrderProductDTO();
        orderProduct.setNumber(1);

        // 优先使用前台产品
        this.fillProductId(orderProduct, product, createOrderDTO.getChannelId());

        // 产品校验
        boolean checkProduct = false;
        do {
            ProductBaseQuery productDIO = new ProductBaseQuery();
            if (Objects.equals(orderProduct.getProductShowType(),GlobalConsts.YES)) {
                productDIO.setShowType(GlobalConsts.YES);
                productDIO.setProductId(orderProduct.getShowProductId());
            } else {
                productDIO.setProductId(orderProduct.getProductId());
            }

            // 查询产品是否存在
            ResponseDTO<List<ProductBaseDRO>> productListResponseDTO = productForeignListRemoteService.listBaseDROByQuery(productDIO);
            if (!productListResponseDTO.isSuccess()&&CollectionUtils.isEmpty(productListResponseDTO.getData())) {
                break;
            }

            // 如果是前台产品则判断映射的后台产品是否存在
            DefaultEcProductQuery defaultEcProductQuery = new DefaultEcProductQuery();
            defaultEcProductQuery.setProductIdList(Lists.newArrayList(productDIO.getProductId()));
            defaultEcProductQuery.setShowType(BaseProductConsts.ERP_SHOW_TYPE);
            productListResponseDTO = productForeignListRemoteService.listEcErpProductByQuery(defaultEcProductQuery);
            if (!productListResponseDTO.isSuccess()&&CollectionUtils.isEmpty(productListResponseDTO.getData())) {
                break;
            }

            checkProduct = true;
        } while(false);

        if (!checkProduct) {
            log.info("【{}】产品校验失败，产品:[{}]-->其他",SogouConsts.CHANNEL_NAME, product);
            orderProduct.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
            orderProduct.setProductShowType(GlobalConsts.NO);
            orderProduct.setShowProductId(0);
        }

        // 产品列表
        List<OrderProductDTO> list = new LinkedList<>();
        list.add(orderProduct);

        // 设置产品信息
        createOrderDTO.setOrderProductList(list);
    }

    /**
     * 解析并设置产品id和产品类型
     * @param orderProductDTO
     * @param product
     * @param channelId
     */
    private void fillProductId(OrderProductDTO orderProductDTO, String product, Integer channelId) {

        Integer productId = OrderConsts.CHANNEL_DISABLED_PRODUCT_ID;
        boolean showProduct = false;

        do {
            if (StringUtil.isBlank(product)) {
                break;
            }

            // 先通过接口查询渠道产品映射
            int idx = product.lastIndexOf(',');
            String productName = (idx >= 0 && idx < (product.length()-1)) ? product.substring(idx) : product;
            List<ChannelProductMapDTO> channelProductMapDTOList = productMappingBService.listChannelProductMapping(channelId,productName,null);
            if (CollectionUtil.isNotNullOrEmpty(channelProductMapDTOList)) {
                productId = channelProductMapDTOList.get(0).getProductId();
                if (Objects.equals(channelProductMapDTOList.get(0).getShowType(), GlobalConsts.YES)) {
                    showProduct = true;
                }
                break;
            }

            // 优先使用前台产品
            /*productId = SogouProductMap.getShowProductId(product);
            if (NumberUtil.isNotNullOrZero(productId)) {
                showProduct = true;
                break;
            }*/

            // 没匹配，则设为其他 xiewenbing 2021/11/125
            productId = OrderConsts.CHANNEL_DISABLED_PRODUCT_ID;
        } while (false);

        if (showProduct) {
            orderProductDTO.setShowProductId(productId);
            orderProductDTO.setProductShowType(GlobalConsts.YES);
        } else {
            orderProductDTO.setProductId(productId);
        }
    }

    /**
     * 读取或设置线索缓存数据
     *
     * @param clueId
     * @param op
     * @return
     */
    private Long setRedisClueData(Long clueId, int op) {

        String redisKey = String.format(RedisKeyConsts.SOGOU_CLUE_REDIS_KEY,clueId.toString());
        Long value = 0L;
        switch (op) {
            case GlobalConsts.YES:
                value = redisManager.incr(redisKey);

                // 有效期为5分钟
                redisManager.expire(redisKey,300);
                break;
            case GlobalConsts.NO:
                value = redisManager.decr(redisKey);
                break;
            default:
                redisManager.del(redisKey);
        }

        return value;
    }

}
